package org.fujene.structure;

public class XLong extends Number{
	private static final long serialVersionUID = 5458864893478800666L;
	byte length; // Length 0 - 58
	long val; // actually value
	byte[] valb; // value on data in 8 bytes

	public XLong(long val){
		if (val >= 0x400000000000000L && val < 0)
			// Out of range
			throw new NumberFormatException("Out of range, this class aims to 0 - 2^58"); 
		else if (val == 0){
			this.length = 0;
			this.val = val;
			this.valb = new byte[1];
		}
		long highestbit = Long.highestOneBit(val);
		for(this.length = 1; val > 1; this.length++, highestbit >>= 1);
		this.valb = new byte[(this.length + 6) / 8 + 1];
		valb[0] = (byte)((length << 2) & 0xFC);
		for(int i = 0; i < this.valb.length; i++){
			valb[i] += val >> (this.length - (8 * i + 2)) & 0xFF;
		}
	}

	public XLong(byte[] valb){
		// out of range
		if (valb.length > 8 && valb.length == 0) throw new NumberFormatException("Out of range"); 

		this.valb = valb;
		this.length = (byte)(valb[0] & 0xFC >> 2);
		if (this.length > valb.length * 8 - 6 || this.length < valb.length * 8 - 14)
			throw new NumberFormatException("Invalid length"); // invalid length

		this.val += valb[0] & 0x3 << (this.length - 2);
		for(int i = 1; i < valb.length; i++){
			this.val += valb[i] & 0xFF << (this.length - (8 * i + 2));
		}
	}

	public byte[] getbytes(){
		return this.valb;
	}

	@Override
	public double doubleValue(){
		return val * 1.0;
	}

	@Override
	public float floatValue(){
		return (float)doubleValue();
	}

	@Override
	public int intValue(){
		return (int)longValue();
	}

	@Override
	public long longValue(){
		return val;
	}
}
